home *** CD-ROM | disk | FTP | other *** search
- { ------------------- Boosters ------------------- }
- { v1.0 }
- { }
- { Utilities for Turbo Pascal (tm) }
- { }
- { Copyright (C) 1985 }
- { All Rights Reserved }
- { }
- { by }
- { }
- { George Smith }
- { 609 Candlewick Lane }
- { Lilburn, GA 30247 }
- { (404) 923-6879 }
- { }
- { }
- { }
- { Boosters users: A $25 contribution would be appreciated }
- { if you find these utilities of value. }
- { }
- { Or if you prefer, become a registered }
- { user for $35 and receive a printed users }
- { guide, update notices, and the latest }
- { version of Boosters. }
- { }
- { Turbo Pascal is a Registered Trademark of Borland, Inc. }
- { }
- {---------------------------------------------------------------}
-
- { ----------------------------------------------
- EXEC invokes compiled programs and batch files
- then returns control to caller.
- ---------------------------------------------- }
- Procedure Exec ( VAR FileDesc, CommandLine : AnyString;
- VAR Code : Integer);
- external 'TBX.COM';
-
- { ------------------------
- FILLHEAP fills heap page
- character/attribute
- block
- ------------------------ }
- Procedure FillHeap ( Page : HeapBuf;
- X1 : RowType;
- Y1 : ColumnType;
- X2 : RowType;
- Y2 : ColumnType;
- C : Char;
- Att : Byte); external 'FillHeap.com';
- { Fill Page from (X1,Y1) to (X2,Y2)
- with C character and Att byte }
-
- { ---------------
- CENTER a string
- --------------- }
-
- Function CENTER ( A : AnyString;
- N : Integer;
- Pad : Char ) : AnyString;
- { AnyString is type String[255] }
-
- begin
- InLine ($1E/ $8D/$9E/$08/$01/ $8B/$46/$06/ $36/$88/$07/ $43/
- $8A/$4E/$08/ $30/$ED/ $29/$C8/ $77/$05/ $31/$C0/ $EB/$12/$90/
- $D1/$E8/ $50/ $8B/$FB/ $8B/$46/$04/ $8B/$4E/$06/ $16/ $07/
- $FC/ $F3/$AA/ $58/ $01/$C3/ $8B/$FB/ $8D/$76/$09/ $16/ $1F/
- $8A/$4E/$08/ $30/$ED/ $FC/ $F3/$A4/ $1F);
- end { Center };
-
-
- { ---------------------------------------------------
- PUTSTR - Write a string directly to display memory
- --------------------------------------------------- }
-
- Procedure PutStr ( HV : Char;
- S : AnyString;
- X : ColumnType;
- Y : RowType;
- Att : Byte );
-
- begin
- InLine ($1E/ $BB/$49/$04/ $31/$C0/ $8E/$D8/ $8A/$07/ $3C/$07/ $75/$06/
- $BA/$00/$B0/ $EB/$0C/$90/ $BA/$DA/$03/ $EC/ $24/$08/ $74/$FB/
- $BA/$00/$B8/ $8E/$C2/ $8B/$5E/$08/ $09/$DB/ $74/$0C/ $4B/
- $8B/$46/$06/ $48/ $8A/$F0/ $8A/$D3/ $EB/$05/$90/ $B4/$03/
- $CD/$10/ $8A/$DE/ $30/$FF/ $8B/$C3/ $B1/$07/ $D3/$E0/ $B1/$05/
- $D3/$E3/ $01/$C3/ $8A/$C2/ $30/$E4/ $D1/$E0/ $01/$C3/ $8B/$FB/
- $8A/$4E/$0A/ $30/$ED/ $8D/$76/$0B/ $16/ $1F/ $8A/$66/$04/
- $8B/$96/$0A/$01/ $80/$FA/$76/ $74/$0A/ $80/$FA/$56/ $74/$05/
- $31/$D2/ $EB/$04/$90/ $BA/$9E/$00/ $FC/ $8A/$04/ $AB/ $01/$D7/
- $46/ $E2/$F8/ $09/$D2/ $74/$04/ $81/$EF/$9E/$00/ $8B/$C7/
- $31/$D2/ $BB/$A0/$00/ $F7/$F3/ $D0/$EA/ $8A/$F0/ $B4/$02/
- $CD/$10/ $1F/$5D);
- end { PutStr };
-
- { -------------------------------------------------
- PUTHEAP - Write a string to Page [n] of the heap
- ------------------------------------------------- }
-
- Procedure PutHeap ( PAGE : HeapBuf;
- HV : Char;
- S : AnyString;
- X : ColumnType;
- Y : RowType;
- Att : Byte );
- external 'PutHeap.com';
-
- { -------------------------------
- COPIES characters into a string
- ------------------------------- }
- Function COPIES (C : Char;
- N : Integer ): AnyString;
- { AnyString is Type string[255] }
- begin
- InLine ($16/ $07/ $8B/$4E/$04/ $88/$4E/$08/ $8B/$46/$06/ $8D/$7E/$09/
- $FC/ $F3/$AA );
- end { Copies };
-
-
- { ------------------------------------------
- COPYSTR returns N concatenated copies of S
- ------------------------------------------ }
- Function CopyStr ( S : AnyString;
- N : Integer ) : AnyString;
-
- Begin
- InLine ($1E/ $8B/$4E/$04/ $83/$F9/$00/ $7F/$09/
- $C7/$86/$06/$01/$00/$00/ $EB/$46/$90/ $8A/$56/$06/ $30/$F6/
- $51/ $8B/$C2/ $49/ $83/$F9/$00/ $74/$04/ $01/$D0/ $E2/$FC/
- $8B/$CA/ $5A/ $3D/$FF/$00/ $76/$06/ $B8/$FF/$00/ $EB/$07/$90/
- $3C/$00/ $73/$02/ $31/$C0/ $88/$86/$06/$01/ $3C/$00/ $74/$17/
- $8C/$D3/ $8E/$C3/ $8E/$DB/ $8D/$BE/$07/$01/ $8D/$76/$07/ $FC/
- $51/ $56/ $F3/$A4/ $5E/ $59/ $4A/ $75/$F7/ $1F );
- end { CopyStr };
-
-
-
- { --------------------------------
- LEFT justify a string in a field
- -------------------------------- }
- Function LEFT ( S : AnyString;
- N : Integer;
- Pad : Char ) : AnyString;
- { AnyString is Type string[255] }
- begin
- InLine ($1E/ $8D/$76/$09/ $8D/$9E/$08/$01/ $8B/$46/$06/ $36/$88/$07/
- $43/ $8A/$4E/$08/ $30/$ED/ $29/$C8/ $77/$05/ $31/$C0/
- $EB/$0F/$90/ $8B/$FB/ $01/$CF/ $8B/$C8/ $8B/$46/$04/ $16/ $07/
- $FC/ $F3/$AA/ $8B/$FB/ $16/ $1F/ $8A/$4E/$08/ $30/$ED/ $FC/
- $F3/$A4/ $1F );
- end { Left };
-
- { --------------------------------
- RIGHT justify a string in a field
- -------------------------------- }
- Function RIGHT ( S : AnyString;
- N : Integer;
- Pad : Char ) : AnyString;
- { AnyString is Type string[255] }
- begin
- InLine ($1E/ $8C/$D0/ $8E/$C0/ $8E/$D8/ $8D/$BE/$09/$01/ $8B/$46/$06/
- $88/$86/$08/$01/ $8A/$4E/$08/ $30/$ED/ $8D/$76/$09/ $01/$CE/
- $4E/ $29/$C8/ $77/$06/ $8B/$4E/$06/ $EB/$0C/$90/ $8B/$C8/
- $8B/$46/$04/ $FC/ $F3/$AA/ $8A/$4E/$08/ $01/$CF/ $4F/ $FD/
- $F3/$A4/ $1F/$5D);
- end { Right };
-
- { ------------------------------------------------
- COPYBLK copies one part of the screen to another
- ------------------------------------------------ }
- Procedure COPYBLK ( X1 : ColumnType;
- Y1 : RowType;
- X2 : ColumnType;
- Y2 : RowType;
- X3 : ColumnType;
- Y3 : RowType );
-
- { Copies block defined by upper left and lower right
- coordinates (X1,Y1),(X2,Y2) to a block beginning
- at upper left coordinates (X3,Y3). }
-
- begin
- InLine ($1E/ $BB/$49/$04/ $31/$C0/ $8E/$D8/ $8A/$07/ $3C/$07/ $75/$06/
- $BA/$00/$B0/ $EB/$0C/$90/ $BA/$DA/$03/ $EC/ $24/$08/ $74/$FB/
- $BA/$00/$B8/ $52/ $8B/$5E/$0C/ $4B/ $8B/$D3/ $B1/$07/ $D3/$E2/
- $B1/$05/ $D3/$E3/ $01/$D3/ $8B/$46/$0E/ $48/ $D1/$E0/ $01/$C3/
- $8B/$F3/ $1F/ $1E/ $8B/$5E/$04/ $4B/ $8B/$D3/ $B1/$07/
- $D3/$E2/ $B1/$05/ $D3/$E3/ $01/$D3/ $8B/$46/$06/ $48/ $D1/$E0/
- $01/$C3/ $8B/$FB/ $07/ $8B/$46/$0C/ $8B/$56/$08/ $29/$C2/ $42/
- $8B/$46/$0E/ $8B/$4E/$0A/ $29/$C1/ $41/ $51/ $FC/ $F3/$A5/
- $59/ $4A/ $74/$0F/ $8B/$D9/ $D1/$E3/ $B8/$A0/$00/ $29/$D8/
- $01/$C6/ $01/$C7/ $EB/$E9/ $1F);
- end { CopyBlk };
-
- Procedure CblkHeap ( Page : HeapBuf;
- X1 : ColumnType;
- Y1 : RowType;
- X2 : ColumnType;
- Y2 : RowType;
- X3 : ColumnType;
- Y3 : RowType ); external 'CblkHeap.Com';
-
- { ------------------------------------------------
- MOVEBLK moves one part of the screen to another
- ------------------------------------------------ }
- Procedure MOVEBLK ( X1 : ColumnType;
- Y1 : RowType;
- X2 : ColumnType;
- Y2 : RowType;
- X3 : ColumnType;
- Y3 : RowType );
-
- { Moves block defined by upper left and lower right
- coordinates (X1,Y1),(X2,Y2) to a block beginning
- at upper left coordinates (X3,Y3). The orginal block
- is erased. }
-
- begin
- InLine ($1E/ $8B/$46/$0C/ $8B/$4E/$08/ $29/$C1/ $41/ $8B/$46/$0E/
- $8B/$56/$0A/ $29/$C2/ $42/ $D1/$E2/ $8B/$D9/ $29/$D4/ $E2/$FC/
- $8C/$D0/ $8E/$C0/ $8B/$FC/ $52/ $53/ $BB/$49/$04/ $31/$C0/
- $8E/$D8/ $8A/$07/ $3C/$07/ $75/$06/ $BA/$00/$B0/ $EB/$0C/$90/
- $BA/$DA/$03/ $EC/ $24/$08/ $74/$FB/ $BA/$00/$B8/ $8E/$DA/
- $8B/$76/$0C/ $4E/ $8B/$D6/ $B1/$07/ $D3/$E2/ $B1/$05/ $D3/$E6/
- $01/$D6/ $8B/$46/$0E/ $48/ $D1/$E0/ $01/$C6/ $5A/ $59/
- $D1/$E9/ $1E/ $56/ $52/ $51/ $B8/$A0/$00/ $29/$C8/ $29/$C8/
- $FC/ $51/ $F3/$A5/ $59/ $4A/ $74/$04/ $01/$C6/ $EB/$F5/ $59/
- $5A/ $5F/ $07/ $52/ $51/ $BB/$A0/$00/ $29/$CB/ $29/$CB/
- $B8/$20/$0E/ $FC/ $51/ $F3/$AB/ $59/ $4A/ $74/$04/ $01/$DF/
- $EB/$F5/ $8B/$7E/$04/ $4F/ $8B/$D7/ $B1/$07/ $D3/$E2/ $B1/$05/
- $D3/$E7/ $01/$D7/ $8B/$46/$06/ $48/ $D1/$E0/ $01/$C7/ $59/
- $5A/ $8B/$F4/ $8C/$D0/ $8E/$D8/ $B8/$A0/$00/ $29/$C8/ $29/$C8/
- $FC/ $51/ $F3/$A5/ $59/ $4A/ $74/$04/ $01/$C7/ $EB/$F5/
- $8B/$E5/ $83/$EC/$04/ $1F/$5D);
- end { MoveBlk };
-
- Procedure MBLKHEAP ( Page : HeapBuf;
- X1 : ColumnType;
- Y1 : RowType;
- X2 : ColumnType;
- Y2 : RowType;
- X3 : ColumnType;
- Y3 : RowType); external 'MblkHeap.Com';
-
- { ---------------------------------------------
- REMBLK blanks a specified area of the display
- --------------------------------------------- }
- Procedure REMBLK ( X1,Y1,X2,Y2 : Integer);
- begin
- InLine ($1E/ $8B/$46/$08/ $8B/$56/$04/ $29/$C2/ $42/ $52/ $8B/$46/$0A/
- $8B/$4E/$06/ $29/$C1/ $41/ $51/ $BB/$49/$04/ $31/$C0/ $8E/$D8/
- $8A/$07/ $3C/$07/ $75/$06/ $BA/$00/$B0/ $EB/$0C/$90/
- $BA/$DA/$03/ $EC/ $24/$08/ $74/$FB/ $BA/$00/$B8/ $8E/$C2/
- $8B/$7E/$08/ $4F/ $8B/$D7/ $B1/$07/ $D3/$E2/ $B1/$05/ $D3/$E7/
- $01/$D7/ $8B/$46/$0A/ $48/ $D1/$E0/ $01/$C7/ $59/ $5A/
- $B8/$20/$0E/ $FC/ $51/ $F3/$AB/ $59/ $4A/ $74/$0A/
- $81/$C7/$A0/$00/ $29/$CF/ $29/$CF/ $EB/$EF/ $1F);
- end { RemBlk };
-
- { ---------------------------------------------
- SETATT sets attribute byte for specified area
- --------------------------------------------- }
- Procedure SETATT ( X1,Y1,X2,Y2 : Integer;
- Attribute : Byte);
- begin
- InLine ($1E/ $8B/$46/$0A/ $8B/$56/$06/ $29/$C2/ $42/ $52/ $8B/$46/$0C/
- $8B/$4E/$08/ $29/$C1/ $41/ $51/ $BB/$49/$04/ $31/$C0/ $8E/$D8/
- $8A/$07/ $3C/$07/ $75/$06/ $BA/$00/$B0/ $EB/$0C/$90/
- $BA/$DA/$03/ $EC/ $24/$08/ $74/$FB/ $BA/$00/$B8/ $8E/$C2/
- $8B/$7E/$0A/ $4F/ $8B/$D7/ $B1/$07/ $D3/$E2/ $B1/$05/ $D3/$E7/
- $01/$D7/ $8B/$46/$0C/ $48/ $D1/$E0/ $01/$C7/ $47/ $59/ $5A/
- $8B/$46/$04/ $FC/ $51/ $AA/ $47/ $E2/$FC/ $59/ $4A/ $74/$0A/
- $81/$C7/$A0/$00/ $29/$CF/ $29/$CF/ $EB/$ED/ $1F/$5D);
- end { SetAtt };
-
-
- { ----------------------------------------------
- HEAPAT sets attribute byte on Page [n] of heap
- ---------------------------------------------- }
- Procedure HEAPAT ( Page : HeapBuf;
- X1,Y1,X2,Y2 : Integer;
- Attribute : Byte);
- external 'Heapat.com';
-
- { ------------------------------------------------
- MOVEBG moves one part of the screen to another,
- while preserving the background.
- ------------------------------------------------ }
- Procedure MOVEBG ( Page : HeapBuf;
- X1 : ColumnType;
- Y1 : RowType;
- X2 : ColumnType;
- Y2 : RowType;
- X3 : ColumnType;
- Y3 : RowType );
- external 'Movebg.com';
-
- { Type HeapBuf = ^AnyBuf;
- AnyBuf = record
- Screen : array[1..4000] of byte;
- end;
-
- Moves block defined by upper left and lower right
- coordinates (X1,Y1),(X2,Y2) to a block beginning
- at upper left coordinates (X3,Y3). The orginal
- block is saved, the background 'Page' refreshed,
- then the block is redisplayed at its new position. }
-
-
- { ----------------------------------------------
- FINDSTR searches for the first occurrence of S
- in video memory beginning from X,Y.
- ---------------------------------------------- }
- Procedure FindStr ( X : ColumnType;
- Y : RowType;
- S : AnyString;
- N : Integer;
- var Ecode : Integer ); external 'FindStr.com';
- {
- Ecode = 0 if S is found on screen
- Ecode = 1 if S not found
- if N = 0, cursor placed at S[1]
- if N < 0, cursor placed at Nth position from left end of S
- if N > 0, cursor placed at Nth position from right end of S }
-
- { -----------------------------------------
- FSTRHEAP searches Page on the heap for
- the first occurrence of S. If S found,
- FstrHeap sets X,Y to the address of S[1].
- If not found, X = 0.
- ----------------------------------------- }
- Procedure FstrHeap ( Page : HeapBuf;
- S : AnyString;
- var X : ColumnType;
- var Y : RowType ); external 'FstrHeap.com';
-
-
- { ------------------------------------------------
- GETSTR reads string at X,Y into S for length LEN
- ------------------------------------------------ }
- Procedure GETSTR ( HV : Char;
- VAR S : AnyString;
- X : ColumnType;
- Y : RowType;
- LEN : Integer);
- external 'GetStr.com';
-
- { If X=Y=0, then read begins at current cursor
- position. Otherwise read begins at (X,Y).
- HV = 'V' or 'v', read is top-to-bottom.
- Otherwise read is left-to-right.
- On exit, cursor points to one beyond last
- byte read. }
-
- Procedure GETHEAP ( Page : HeapBuf;
- HV : Char;
- VAR S : AnyString;
- X : ColumnType;
- Y : RowType;
- LEN : Integer ); external 'GetHeap.com';
-
- { GetHeap gets strings from the heap. X,Y must be valid
- coordinates--zero not allowed. GetHeap is useful for
- getting small portions of the heap }
-
- { ------------------------------------------------
- UPPER function converts alphabetics to uppercase
- ------------------------------------------------ }
- Function UPPER ( S : AnyString) : AnyString;
- begin
- InLine ($1E/ $8A/$4E/$04/ $30/$ED/ $8D/$76/$05/ $8D/$BE/$04/$01/
- $36/$88/$0D/ $80/$F9/$00/ $76/$18/ $47/ $8C/$D0/ $8E/$D8/
- $8E/$C0/ $FC/ $8A/$04/ $3C/$61/ $72/$06/ $3C/$7A/ $77/$02/
- $2C/$20/ $AA/ $46/ $E2/$F0/ $1F);
- end { Upper };
-
- { --------------------------------------------
- OVERSTR overlays and pads target string with
- new string
- -------------------------------------------- }
- Function OVERSTR ( NEW, TARGET : AnyString;
- N, LEN : Integer;
- PAD : Char) : AnyString;
-
- { NEW overlays TARGET beginning at position N of
- TARGET, for a length of LEN. If LEN exceeds the
- length of NEW, NEW is padded on the right with
- PAD. If N exceeds the length of TARGET, left-
- padding occurs before NEW is written. }
- begin
- InLine ($1E/ $8C/$D0/ $8E/$C0/ $8E/$D8/ $8A/$4E/$0A/ $30/$ED/
- $8D/$76/$0B/ $8D/$BE/$0B/$02/ $FC/ $F3/$A4/ $8A/$5E/$0A/
- $30/$FF/ $8B/$4E/$06/ $83/$F9/$00/ $7C/$71/ $8B/$56/$08/
- $83/$FA/$00/ $7C/$69/ $8D/$BE/$0B/$02/ $39/$DA/ $76/$30/
- $81/$FA/$00/$FF/ $76/$03/ $BA/$00/$01/ $8B/$CA/ $29/$D9/ $49/
- $8B/$46/$04/ $01/$DF/ $F3/$AA/ $8D/$BE/$0B/$02/ $8B/$4E/$06/
- $01/$D1/ $81/$F9/$FF/$00/ $77/$06/ $8B/$4E/$06/ $EB/$07/$90/
- $B9/$FF/$00/ $29/$D1/ $41/ $8A/$86/$0A/$01/ $30/$E4/ $51/
- $39/$C1/ $72/$02/ $8B/$C8/ $8D/$B6/$0B/$01/ $01/$D7/ $4F/
- $F3/$A4/ $59/ $39/$C1/ $76/$16/ $01/$D0/ $3D/$FF/$00/ $73/$0F/
- $51/ $8A/$86/$0A/$01/ $30/$E4/ $29/$C1/ $8B/$46/$04/ $F3/$AA/
- $59/ $8D/$8E/$0B/$02/ $29/$CF/ $39/$DF/ $77/$02/ $8B/$FB/
- $8B/$C7/ $88/$86/$0A/$02/ $1F/$5D);
- end { OverStr };
-
- { --------------------------------------
- DOWS returns day of week for any valid
- Gregorian Date
- -------------------------------------- }
- Function DOWS( MM, DD, CCYY : Integer) : AnyString;
-
- begin
- InLine ($1E/ $E8/$A8/$00/ $EB/$0D/$90/ $00/$03/$02/$05/$00/$03/
- $05/$01/$04/$06/$02/$04/ $83/$C3/$03/ $8B/$FB/ $8B/$5E/$08/
- $8B/$4E/$06/ $8B/$56/$04/ $83/$FB/$03/ $73/$01/ $4A/ $01/$DF/
- $4F/ $2E/$02/$0D/ $8B/$C2/ $BB/$64/$00/ $30/$FF/ $F6/$F3/ $51/
- $50/ $B1/$02/ $D2/$CC/ $B1/$06/ $D2/$EC/ $8A/$DC/ $58/
- $B1/$02/ $D2/$C8/ $B1/$06/ $D2/$E8/ $B1/$02/ $8A/$D4/ $D2/$EA/
- $59/ $00/$D0/ $B7/$05/ $F6/$E7/ $30/$FF/ $01/$D8/ $01/$C8/
- $BA/$07/$00/ $F6/$F2/ $8A/$C4/ $30/$E4/ $E8/$42/$00/
- $EB/$46/$90/ $53/$75/$6E/$64/$61/$79/$20/$20/$20/
- $4D/$6F/$6E/$64/$61/$79/$20/$20/$20/
- $54/$75/$65/$73/$64/$61/$79/$20/$20/
- $57/$65/$64/$6E/$65/$73/$64/$61/$79/
- $54/$68/$75/$72/$73/$64/$61/$79/$20/
- $46/$72/$69/$64/$61/$79/$20/$20/$20/
- $53/$61/$74/$75/$72/$64/$61/$79/$20/ $8B/$DC/ $36/$8B/$1F/
- $C3/ $83/$C3/$03/ $8B/$F3/ $B9/$09/$00/ $F6/$E1/ $01/$C6/ $0E/
- $1F/ $16/ $07/ $88/$4E/$0A/ $8D/$7E/$0B/ $FC/ $F3/$A4/
- $1F/$5D);
- end { Dows };
-
- { -------------------------------------------
- STRIP function removes leading and trailing
- characters from a string.
- ------------------------------------------- }
- Function STRIP ( S : AnyString;
- C : Char) : AnyString;
- { Removes all leading and trailing
- C characters from S }
- begin
- InLine ($1E/ $8D/$7E/$07/ $8A/$4E/$06/ $30/$ED/ $8C/$D0/ $8E/$C0/
- $8B/$46/$04/ $83/$F9/$01/ $77/$0E/ $8A/$5E/$07/ $30/$FF/
- $39/$D8/ $74/$35/ $8B/$D7/ $EB/$1D/$90/ $FC/ $F3/$AE/ $E3/$2B/
- $4F/ $8B/$D7/ $8A/$4E/$06/ $30/$ED/ $8D/$7E/$07/ $01/$CF/ $4F/
- $FD/ $F3/$AE/ $47/ $8B/$CF/ $29/$D1/ $41/ $88/$8E/$06/$01/
- $8B/$F2/ $8D/$BE/$07/$01/ $8C/$D0/ $8E/$D8/ $FC/ $F3/$A4/
- $EB/$07/$90/ $C7/$86/$06/$01/$00/$00/ $1F/$5D);
- end { Strip };
-
- { ---------------------
- Upper Left Box
- --------------------- }
- Procedure BOXUL ( Start_Col, Start_Row,
- End_Col, End_Row, Style : Integer;
- Attribute : Byte);
-
- Var
- Ver_Adj, Hor_Adj, Num_Col, Num_Row : Integer;
-
- Const
- { DOWN LL OVER LR UR UL }
- s : array[1..4,1..6] of char = ((#179,#192,#196,#217,#191,#218),
- (#186,#200,#205,#188,#187,#201),
- (#186,#211,#196,#189,#183,#214),
- (#179,#212,#205,#190,#184,#213));
-
- begin
- if (style < 1) or (style > 4) then
- style := 1;
- Num_Col := End_Col - Start_Col + 1;
- Num_Row := End_Row - Start_Row + 1;
- if Num_Col <= 2 then
- Num_Col := 3;
- if Num_Row <= 2 then
- Num_Row := 3;
- Ver_Adj := Num_Row - 2;
- Hor_Adj := Num_Col - 2;
-
- PUTSTR ( V, s[style,6],
- Start_Col, Start_Row, Attribute); { UL Corner }
-
- PUTSTR ( V, COPIES( s[style,1], Ver_Adj),
- Start_Col, Start_Row + 1, Attribute); { Left Side }
-
- PUTSTR ( V, s[style,2],
- Start_Col, End_Row, Attribute); { LL Corner }
-
- PUTSTR ( H, COPIES( s[style,3], Hor_Adj),
- Start_Col + 1, End_Row, Attribute); { Bottom }
-
- PUTSTR ( V, s[style,4],
- End_Col, End_Row, Attribute); { LR Corner }
-
- PUTSTR ( V, COPIES( s[style,1],Ver_Adj),
- End_Col, Start_Row + 1, Attribute); { Right Side }
-
- PUTSTR ( V, s[style,5],
- End_Col, Start_Row, Attribute); { UR Corner }
-
- PUTSTR ( H, COPIES( s[style,3],Hor_Adj),
- Start_Col + 1, Start_Row, Attribute); { Top }
-
- end { Boxul };
-
- { --------------------------------
- BOXHEAP builds a box on the heap
- at Page [n]
- -------------------------------- }
- Procedure BoxHeap ( Page : HeapBuf;
- Start_Col, Start_Row,
- End_Col, End_Row, Style : Integer;
- Attribute : Byte);
-
- Var
- Ver_Adj, Hor_Adj, Num_Col, Num_Row : Integer;
-
- Const
- { DOWN LL OVER LR UR UL }
- s : array[1..4,1..6] of char = ((#179,#192,#196,#217,#191,#218),
- (#186,#200,#205,#188,#187,#201),
- (#186,#211,#196,#189,#183,#214),
- (#179,#212,#205,#190,#184,#213));
-
- begin
- if (style < 1) or (style > 4) then
- style := 1;
- Num_Col := End_Col - Start_Col + 1;
- Num_Row := End_Row - Start_Row + 1;
- if Num_Col <= 2 then
- Num_Col := 3;
- if Num_Row <= 2 then
- Num_Row := 3;
- Ver_Adj := Num_Row - 2;
- Hor_Adj := Num_Col - 2;
-
- PutHeap ( Page, V, s[style,6],
- Start_Col, Start_Row, Attribute); { UL Corner }
-
- PutHeap ( Page, V, COPIES( s[style,1], Ver_Adj),
- Start_Col, Start_Row + 1, Attribute); { Left Side }
-
- PutHeap ( Page, V, s[style,2],
- Start_Col, End_Row, Attribute); { LL Corner }
-
- PutHeap ( Page, H, COPIES( s[style,3], Hor_Adj),
- Start_Col + 1, End_Row, Attribute); { Bottom }
-
- PutHeap ( Page, V, s[style,4],
- End_Col, End_Row, Attribute); { LR Corner }
-
- PutHeap ( Page, V, COPIES( s[style,1],Ver_Adj),
- End_Col, Start_Row + 1, Attribute); { Right Side }
-
- PutHeap ( Page, V, s[style,5],
- End_Col, Start_Row, Attribute); { UR Corner }
-
- PutHeap ( Page, H, COPIES( s[style,3],Hor_Adj),
- Start_Col + 1, Start_Row, Attribute); { Top }
-
- end { BoxHeap };
-
-
- { ----------------------
- TIMER Boolean Function
- ---------------------- }
- Function Timer ( Limit : integer) : Boolean;
-
- { Note: Globals are:
- Type
- Result = record
- AX, BX, CX, DX, BP,
- SI, DI, DS, ES, Flags : Integer;
- end;
- var
- regs : result;
- TimeElapsed,
- SaveElapsed : Integer;
- StartElapsed : Boolean = FALSE;
- }
- var
- SecondsReading : Integer;
-
- begin
- with regs do
- begin
- if Limit <= 0 then
- Timer := TRUE
- else
- begin
- Timer := FALSE;
- ax := $2C00;
- intr($21,regs);
-
- if StartElapsed = FALSE then
- begin
- SaveElapsed := hi(dx);
- TimeElapsed := 0;
- StartElapsed := TRUE;
- ax := $2D00; { Set time . . . }
- dx := Swap(SaveElapsed); { With hundredths = 0 . . . }
- intr($21,regs); { so that we start from 0 }
- delay(70); { Helps DOS 3.1 work right }
- end
- else
- if SaveElapsed <> hi(dx) then
- begin
- SecondsReading := hi(dx);
- if SaveElapsed > SecondsReading then
- SecondsReading := SecondsReading + 60;
- TimeElapsed := TimeElapsed + SecondsReading - SaveElapsed;
- SaveElapsed := hi(dx);
-
- if TimeElapsed >= Limit then
- begin
- Timer := TRUE;
- StartElapsed := FALSE;
- end;
- end;
- end;
- end;
- end { Timer };
-
- { --------------------------
- Display TIME of day at X,Y
- -------------------------- }
- Procedure TimeXY (X : ColumnType;
- Y : RowType ) ;
- var
- hour : integer;
- hr,
- min, sec : string[2];
-
- begin
- with regs do
- begin
- ax := $2C00;
- intr($21,regs);
- hour := hi(cx);
- if hour < 1 then
- hour := 12
- else
- if hour > 12 then
- hour := hour - 12;
- str ( hour, hr );
- str ( lo(cx), min );
- str ( hi(dx), sec );
- if length(min) < 2 then
- min := '0'+min;
- if length(sec) < 2 then
- sec := '0'+sec;
- PutStr( h,hr+':'+min+':'+sec, x,y,14);
- end
- end { TimeXY };
-
- { ---------------
- SET TIME of day
- --------------- }
- Procedure Stime ( hh, mm, ss : integer );
- begin
- with regs do
- begin
- cx := swap(hh);
- cx := cx or mm;
- dx := swap(ss);
- ax := $2D00;
- intr($21,regs);
- end;
- end { Stime };
-
- { -----------------------------------
- SAVESCREEN saves the current screen
- ----------------------------------- }
- Procedure SaveScreen ( Page : HeapBuf);
- external 'Saves.com';
-
- { -------------------------------------
- RESTORESCREEN restores a saved screen
- ------------------------------------- }
- Procedure RestoreScreen ( Page : HeapBuf);
- external 'Restores.com';
-
- { ------------------------------------
- CURSOROFF makes the cursor invisible
- ------------------------------------ }
- Procedure CursorOff;
- begin
- with regs do
- begin
- cx := $2000;
- ax := $0100;
- intr($10,regs);
- end;
- end { CursorOff };
-
- { ---------------------------------
- CURSORON produces a normal cursor
- --------------------------------- }
- Procedure CursorOn;
- begin
- with regs do
- begin
- if VideoStatus = 7 then
- cx := $0C0D { Monochrome }
- else
- cx := $0607; { Color }
- ax := $0100;
- intr($10,regs);
- end;
- end { CursorOn };
-
- { --------------------------------------
- WAIT for Timer to elapse or a KeyPress.
- If KeyPress was HOME key, WAIT waits
- for another KeyPress.
- -------------------------------------- }
- Procedure Wait ( NumberOfSeconds : Integer);
- begin
- repeat until Timer(NumberOfSeconds) or KeyPressed;
- if KeyPressed then
- begin
- read(Kbd,ch);
- StartElapsed := FALSE;
- if (ch = #27) and KeyPressed then
- begin
- read(Kbd,ch);
- if ch = #71 then
- begin
- repeat until KeyPressed;
- read(Kbd,ch);
- if (ch = #27 ) and KeyPressed then
- read(Kbd,ch);
- end;
- end;
- end;
- end { Wait };
-
-
- { --------------------------------
- NSORBIT - Nancy's Orbiting Light
- -------------------------------- }
- Procedure NsOrbit ( StartCol , StartRow,
- EndCol , EndRow,
- Style , NumberOfSeconds : Integer);
- Var
- NumberCols, NumberRows, I,
- RowDelay, ColDelay : Integer;
- begin
-
- RowDelay := 3;
- ColDelay := 1;
- NumberCols := EndCol - StartCol + 1;
- NumberRows := EndRow - StartRow + 1;
-
- BoxUL (StartCol, StartRow, EndCol, EndRow, Style, 14);
-
- repeat
- for i := 0 to NumberCols - 1 do
- begin
- SetAtt ( StartCol+i, StartRow, StartCol+i, StartRow, 14);
- delay(ColDelay);
- SetAtt ( StartCol+i, StartRow, StartCol+i, StartRow, 0);
- delay(ColDelay);
- SetAtt ( EndCol-i, EndRow, EndCol-i, EndRow, 14);
- delay(ColDelay);
- SetAtt ( EndCol-i, EndRow, EndCol-i, EndRow, 0);
- delay(ColDelay);
- end;
-
- for i := 0 to NumberRows - 1 do
- begin
- SetAtt ( EndCol, StartRow+i, EndCol, StartRow+i, 14);
- delay(RowDelay);
- SetAtt ( EndCol, StartRow+i, EndCol, StartRow+i, 0);
- delay(RowDelay);
- SetAtt ( StartCol, EndRow-i, StartCol, EndRow-i, 14);
- delay(RowDelay);
- SetAtt ( StartCol, EndRow-i, StartCol, EndRow-i, 0);
- delay(RowDelay);
- end;
-
- for i := 0 to NumberCols - 1 do
- begin
- SetAtt ( StartCol+i, StartRow, StartCol+i, StartRow, 14);
- delay(ColDelay);
- SetAtt ( StartCol+i, StartRow, StartCol+i, StartRow, 0);
- delay(ColDelay);
- SetAtt ( EndCol-i, EndRow, EndCol-i, EndRow, 14);
- delay(ColDelay);
- SetAtt ( EndCol-i, EndRow, EndCol-i, EndRow, 0);
- delay(ColDelay);
- end;
-
- for i := 0 to NumberRows - 1 do
- begin
- SetAtt ( StartCol, EndRow-i, StartCol, EndRow-i, 14);
- delay(RowDelay);
- SetAtt ( StartCol, EndRow-i, StartCol, EndRow-i, 0);
- delay(RowDelay);
- SetAtt ( EndCol, StartRow+i, EndCol, StartRow+i, 14);
- delay(RowDelay);
- SetAtt ( EndCol, StartRow+i, EndCol, StartRow+i, 0);
- delay(RowDelay);
- end;
- until Timer(NumberOfSeconds) or KeyPressed;
- if KeyPressed then
- begin
- read(Kbd,ch);
- StartElapsed := FALSE;
- end;
- BoxUL (StartCol, StartRow, EndCol, EndRow, Style, 14);
- end { NsOrbit };
-
- { ---------------------------------
- CALENDAR for given month and year
- --------------------------------- }
- Procedure Calendar ( MM, CCYY, StartCol, StartRow : Integer);
- var
- target : string[10];
- year : string[4];
- PreviousMonth,
- NextMonth,
- PreviousMonthLength,
- NumDays,
- Xpos, Ypos, StartDay,
- i, j, day : integer;
- Temp, Months,
- Col, Row : AnyString;
-
- const
- days : array[1..7] of string[2] =
- ('Su','Mo','Tu','We','Th','Fr','Sa');
- MonthLength : array[1..12] of integer =
- (31,28,31,30,31,30,31,31,30,31,30,31);
-
- begin
- target := strip( dows ( mm, 1, ccyy), ' ');
- day := 0;
- repeat
- day := succ(day);
- until (Copy ( target, 1, 2) = days[day]) or (day > 7);
-
- if day <= 7 then
- begin
- Col := #179+#197;
- Col := #194+Col+Col+Col+Col+Col+#179+#193;
- Row := #196+#196+#197;
- Row := #195+Row+Row+Row+Row+Row+Row+#196+#196+#180;
- BoxUL ( StartCol, StartRow+2, StartCol+21, StartRow+14, 1, 14);
- for i := 0 to 5 do
- PutStr ( V, Col, StartCol+3+i*3, StartRow+2, 14);
- for i := 0 to 4 do
- PutStr ( H, Row, StartCol, StartRow+4+i*2, 14);
-
- Months := 'January February March '+
- 'April May June '+
- 'July August September '+
- 'October November December ';
-
- Str (CCYY,year);
- Temp := Copy ( Months, 1+(MM-1)*10, 10);
- Temp := Center ( Strip ( Temp, ' ') + ', '+year ,20,' ');
- PutStr (H, Temp , StartCol + 1, StartRow, 14);
-
- for i := 1 to 7 do
- PutStr (H,days[i] + ' ',
- StartCol+1+(i-1)*3, StartRow+1, 10);
-
- if MM = 1 then
- PreviousMonth := 12
- else
- PreviousMonth := MM - 1;
-
- PreviousMonthLength := MonthLength[PreviousMonth];
- if ( PreviousMonth = 2 ) and ( Abs(1980-CCYY) mod 4 = 0) then
- PreviousMonthLength := succ(PreviousMonthLength);
- Ypos := StartRow + 3;
- if day > 1 then
- begin
- j := PreviousMonthLength - day + 1;
- for i := 1 to day - 1 do
- begin
- j := succ(j);
- str ( j:2, Temp);
- PutStr ( H, Temp , StartCol+1+(i-1)*3, Ypos, 12);
- end;
- for i := 1 to 7 - day + 1 do
- begin
- str ( i:2, Temp);
- PutStr ( H, Temp , StartCol+1+(day-1)*3+(i-1)*3, Ypos, 14);
- end;
- end { day > 1 }
- else
- begin
- j := PreviousMonthLength - 7;
- for i := 1 to 7 do
- begin
- j := succ(j);
- str ( j:2, Temp);
- PutStr ( H, Temp , StartCol+1+(i-1)*3, Ypos, 12);
- end;
- end { day = 1 };
-
- j := 0;
- Ypos := StartRow + 5;
- NumDays := MonthLength[mm];
- if ( MM = 2 ) and ( Abs(1980-CCYY) mod 4 = 0) then
- NumDays := succ(NumDays);
-
- if Day > 1 then
- StartDay := 7 - day + 2
- else
- StartDay := 1;
-
- for i := StartDay to NumDays do
- begin
- Xpos := StartCol+1+j*3;
- Str(i:2,Temp);
- PutStr ( H, Temp, Xpos, Ypos, 14);
- j := succ(j);
- if j = 7 then
- begin
- j := 0;
- Ypos := Ypos + 2;
- end;
- end;
-
- if Day > 1 then
- NextMonth := 42 - ( day - 1 + NumDays)
- else
- NextMonth := 42 - (NumDays + 7);
- for i := 1 to NextMonth do
- begin
- Xpos := StartCol+1+j*3;
- Str(i:2,Temp);
- PutStr ( H, Temp, Xpos, Ypos, 12);
- j := succ(j);
- if j = 7 then
- begin
- j := 0;
- Ypos := Ypos + 2;
- end;
- end;
- end;
- end { Calendar };
-
- { ---------------------------------
- CALHEAP for given month and year
- --------------------------------- }
- Procedure CalHeap ( Page : HeapBuf; MM, CCYY, StartCol, StartRow : Integer);
- var
- target : string[10];
- year : string[4];
- PreviousMonth,
- NextMonth,
- PreviousMonthLength,
- NumDays,
- Xpos, Ypos, StartDay,
- i, j, day : integer;
- Temp, Months,
- Col, Row : AnyString;
-
- const
- days : array[1..7] of string[2] =
- ('Su','Mo','Tu','We','Th','Fr','Sa');
- MonthLength : array[1..12] of integer =
- (31,28,31,30,31,30,31,31,30,31,30,31);
-
- begin
- target := strip( dows ( mm, 1, ccyy), ' ');
- day := 0;
- repeat
- day := succ(day);
- until (Copy ( target, 1, 2) = days[day]) or (day > 7);
-
- if day <= 7 then
- begin
- Col := #179+#197;
- Col := #194+Col+Col+Col+Col+Col+#179+#193;
- Row := #196+#196+#197;
- Row := #195+Row+Row+Row+Row+Row+Row+#196+#196+#180;
- BoxHeap ( Page, StartCol, StartRow+2, StartCol+21, StartRow+14, 1, 14);
- for i := 0 to 5 do
- PutHeap ( Page, V, Col, StartCol+3+i*3, StartRow+2, 14);
- for i := 0 to 4 do
- PutHeap ( Page, H, Row, StartCol, StartRow+4+i*2, 14);
-
- Months := 'January February March '+
- 'April May June '+
- 'July August September '+
- 'October November December ';
-
- Str (CCYY,year);
- Temp := Copy ( Months, 1+(MM-1)*10, 10);
- Temp := Center ( Strip ( Temp, ' ') + ', '+year ,20,' ');
- PutHeap (Page, H, Temp , StartCol + 1, StartRow, 14);
-
- for i := 1 to 7 do
- PutHeap (Page, H,days[i] + ' ',
- StartCol+1+(i-1)*3, StartRow+1, 10);
-
- if MM = 1 then
- PreviousMonth := 12
- else
- PreviousMonth := MM - 1;
-
- PreviousMonthLength := MonthLength[PreviousMonth];
- if ( PreviousMonth = 2 ) and ( Abs(1980-CCYY) mod 4 = 0) then
- PreviousMonthLength := succ(PreviousMonthLength);
- Ypos := StartRow + 3;
- if day > 1 then
- begin
- j := PreviousMonthLength - day + 1;
- for i := 1 to day - 1 do
- begin
- j := succ(j);
- str ( j:2, Temp);
- PutHeap ( Page, H, Temp , StartCol+1+(i-1)*3, Ypos, 12);
- end;
- for i := 1 to 7 - day + 1 do
- begin
- str ( i:2, Temp);
- PutHeap ( Page, H, Temp , StartCol+1+(day-1)*3+(i-1)*3, Ypos, 14);
- end;
- end { day > 1 }
- else
- begin
- j := PreviousMonthLength - 7;
- for i := 1 to 7 do
- begin
- j := succ(j);
- str ( j:2, Temp);
- PutHeap ( Page, H, Temp , StartCol+1+(i-1)*3, Ypos, 12);
- end;
- end { day = 1 };
-
- j := 0;
- Ypos := StartRow + 5;
- NumDays := MonthLength[mm];
- if ( MM = 2 ) and ( Abs(1980-CCYY) mod 4 = 0) then
- NumDays := succ(NumDays);
-
- if Day > 1 then
- StartDay := 7 - day + 2
- else
- StartDay := 1;
-
- for i := StartDay to NumDays do
- begin
- Xpos := StartCol+1+j*3;
- Str(i:2,Temp);
- PutHeap ( Page, H, Temp, Xpos, Ypos, 14);
- j := succ(j);
- if j = 7 then
- begin
- j := 0;
- Ypos := Ypos + 2;
- end;
- end;
-
- if Day > 1 then
- NextMonth := 42 - ( day - 1 + NumDays)
- else
- NextMonth := 42 - (NumDays + 7);
- for i := 1 to NextMonth do
- begin
- Xpos := StartCol+1+j*3;
- Str(i:2,Temp);
- PutHeap ( Page, H, Temp, Xpos, Ypos, 12);
- j := succ(j);
- if j = 7 then
- begin
- j := 0;
- Ypos := Ypos + 2;
- end;
- end;
- end;
- end { CalHeap };
-
- { ------------------------------
- RWORD returns a string with ST
- replacing word N of S.
- ------------------------------ }
- Function RWord ( S : AnyString;
- N : Integer;
- ST : AnyString ) : AnyString;
-
- { A word is any blank-delimited character sequence,
- or a string of non-blanks. There are 7 words in
- this sentence. }
-
- var
- NumWords, start, stop, CurrentAddress, len
- : integer;
- Ts, Ats, Tail
- : AnyString;
- BlankFound
- : Boolean;
-
- begin
- if Length(S) = 0 then
- Rword := ''
- else
- begin
- len := Length(S);
- NumWords := 0;
- start := 1;
- stop := len;
- BlankFound := True;
- CurrentAddress := 0;
- repeat
- CurrentAddress := CurrentAddress + 1;
- if BlankFound then
- begin
- if S[CurrentAddress] <> #32 then
- begin
- BlankFound := false;
- NumWords := succ(NumWords);
- if NumWords = N then
- start := CurrentAddress;
- end;
- end
- else
- if S[CurrentAddress] = #32 then
- begin
- BlankFound := true;
- if NumWords = N then
- stop := CurrentAddress;
- end;
- until (CurrentAddress = len ) or ( stop < len );
- if N > NumWords then
- Rword := S
- else
- begin
- Tail := copy ( S, stop, Length(S)-stop+1 );
- Ts := copy ( S, 1, start-1 );
- Ats := St;
- if (length(Ts) + length(St) + length(Tail)) > 255 then
- Ats := copy ( St, 1, 255 - length(Ts) - length(tail) );
- if S[stop] = #32 then
- Rword := Ts + Ats + Tail
- else
- Rword := Ts + Ats;
- end;
- end;
- end { Rword };
-
- { ------------------------------------------
- WORD returns a string that is word N of S.
- ------------------------------------------ }
- Function Word ( S : AnyString;
- N : Integer ) : AnyString;
-
- var
- NumWords, start, stop, CurrentAddress, len
- : integer;
- Ts
- : AnyString;
- BlankFound
- : Boolean;
-
-
- begin
- if Length(S) = 0 then
- Word := ''
- else
- begin
- NumWords := 0;
- start := 1;
- len := length(S);
- stop := len;
- BlankFound := True;
- CurrentAddress := 0;
-
- repeat
- CurrentAddress := CurrentAddress + 1;
- if BlankFound then
- begin
- if S[CurrentAddress] <> #32 then
- begin
- BlankFound := false;
- NumWords := NumWords + 1;
- if NumWords = N then
- start := CurrentAddress;
- end;
- end
- else
- if S[CurrentAddress] = #32 then
- begin
- BlankFound := true;
- if NumWords = N then
- stop := CurrentAddress;
- end;
- until (stop < len) or (CurrentAddress = len);
-
- if N > NumWords then
- Word := ''
- else
- begin
- if S[stop] <> #32 then
- stop := succ(stop);
- Word := copy ( S, start, stop - start );
- end;
- end;
- end { Word };
-
- { ---------------------------------------
- WORDS returns the number of words in S.
- --------------------------------------- }
- Function Words ( S : AnyString ) : Integer;
- var
- NumWords, CurrentAddress, Len
- : integer;
-
- begin
- S := strip(S,' ');
- Len := Length(S);
- if Len = 0 then
- Words := 0
- else
- begin
- NumWords := 1;
- CurrentAddress := 1;
- for CurrentAddress := 1 to Len do
- if S[CurrentAddress] = #32 then
- NumWords := NumWords + 1;
- Words := NumWords;
- end;
- end { Words };
-
- { ------------------------------------------
- WORDIND returns the position of WordNumber
- in S.
- ------------------------------------------ }
- Function WordInd ( S : AnyString;
- WordNumber : Integer ) : Integer;
-
- { Example: if S = 'I like Turbo Pascal' then
- WordInd ( S, 3 ) is 8. }
-
- var
- NumWords, CurrentAddress, Len, Index
- : integer;
- NonBlank : Boolean;
-
- begin
- Len := Length(S);
- if Len = 0 then
- WordInd := 0
- else
- begin
- Index := 0;
- NumWords := 0;
- CurrentAddress := 0;
- NonBlank := false;
- repeat
- CurrentAddress := CurrentAddress + 1;
- if NonBlank then
- begin
- if S[CurrentAddress] = #32 then
- NonBlank := false;
- end
- else
- if S[CurrentAddress] <> #32 then
- begin
- NumWords := NumWords + 1;
- if NumWords = WordNumber then
- Index := CurrentAddress;
- NonBlank := true;
- end;
- until (CurrentAddress = Len) or (Index > 0);
- WordInd := Index;
- end;
- end { WordInd };
-
- { -------------------------
- SPACE normalizes a string
- ------------------------- }
- Function Space ( S : AnyString ) : AnyString;
-
- { A normalized string has no leading or trailing blanks
- and has only one space between words. }
-
- var
- Ts : AnyString;
- CurrentWord, NumberOfWords : integer;
- begin
- Ts := '';
- NumberOfWords := words(S);
- if NumberOfWords > 0 then
- begin
- for CurrentWord := 1 to NumberOfWords do
- begin
- if CurrentWord <> NumberOfWords then
- Ts := Ts + word ( S, CurrentWord ) + ' '
- else
- Ts := Ts + word ( S,CurrentWord);
- end;
- end;
- Space := Ts;
- end {Space} ;